import { BaseEventManager } from "../event/EventManager";
import { SocketProtoCoder } from "./ISocket";
import { socketManager } from "./SocketManager";

export type SocketConnectCallback = (socket: Socket) => void;
export type SocketCloseCallback = (event: CloseEvent) => void;
export type SocketErrorCallback = (event: Event) => void;

export abstract class Socket extends BaseEventManager<number> {
    protected _name: string;
    public get name(): string {
        return this._name;
    }

    public set name(value: string) {
        this._name = value;
        if (this._name != null) {
            socketManager.set(value, this);
        }
    }

    public abstract get connected(): boolean;

    // 心跳检测
    private _heartBeatEnable: boolean = false;
    private _heartBeatTime: number = 1000 * 5;
    // 心跳协议 id
    private _heartBeatProtoId: number = 0;
    // 心跳的 interval
    private _heartBeatInterval: number = null;
    private _heartBeatPayload: any = null;
    private heartBeatPayload() {
        let payload = this._heartBeatPayload;
        if (payload == null) {
            return null;
        }

        return typeof payload == "function" ? payload() : payload;
    }

    // 消息解析处理器
    protected _protoHandler: SocketProtoCoder = null;
    public get protoHandler(): SocketProtoCoder {
        return this._protoHandler;
    }

    constructor(protoHandler: SocketProtoCoder) {
        super();
        this._protoHandler = protoHandler;
    }

    protected _connectCallback: SocketConnectCallback = null;
    protected _closeCallback: SocketCloseCallback = null;
    protected _errorCallback: SocketErrorCallback = null;
    public connectCallback(callback: SocketConnectCallback) {
        this._connectCallback = callback;
    }

    public closeCallback(callback: SocketCloseCallback) {
        this._closeCallback = callback;
    }

    public errorCallback(callback: SocketErrorCallback) {
        this._errorCallback = callback;
    }

    // 连接
    abstract connect(onConnect?: SocketConnectCallback, onError?: SocketErrorCallback): void;
    // 连接回调
    abstract onConnect(): void;
    // 重连
    abstract reconnect(): any;
    // 发送消息
    abstract send(protoId: number, ...data: any[]): void;
    // 发送并等待 protoId 协议
    abstract sendHalt(protoId: number, ...data: any[]): void;
    // 同 sendHalt，但最后一个参数可以是一个回调，在等待并接受到 protoId 协议后进行回调，它更像是 Http 请求一样，一次请求对应一次回调处理
    abstract request(protoId: number, ...data: any[]): void;
    // 接收回调
    abstract onReceive(...data: any[]): void;
    // 错误回调
    abstract onError(...data: any[]): void;
    // 关闭连接
    abstract close(code: number, ...data: any[]): void;
    // 关闭连接回调
    abstract onClose(...data: any[]): void;

    // 启用心跳检测
    public enableHeartBeat(protoId: number, payload: any = null) {
        this._heartBeatEnable = true;
        this._heartBeatProtoId = protoId;
        this._heartBeatPayload = payload;
        this.startHeartBeat();
    }

    public startHeartBeat(): void {
        if (!this._heartBeatEnable || this._heartBeatInterval) {
            return;
        }

        this._heartBeatInterval = setInterval(() => {
            if (!this.connected) {
                return;
            }

            this.send(this._heartBeatProtoId, this.heartBeatPayload());
        }, this._heartBeatTime);
    }

    public stopHeartBeat(): void {
        if (!this._heartBeatInterval) {
            return;
        }

        clearInterval(this._heartBeatInterval);
        this._heartBeatEnable = false;
        this._heartBeatInterval = 0;
    }
}